import 'dart:convert';
import 'dart:io';
import 'dart:isolate';

import 'package:flutter/cupertino.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:tool/page/common/image_page.dart';
import 'package:tool/utils/file_utils.dart';

import '../../../base/base_model.dart';
import '../../../resources.dart';
import '../m/image_dir_model.dart';

/// created by hcl
/// on 2025/5/9
/// FileManagerModel
/// desc
class ImageManagerModel extends BaseModel {
  String realGenDir = '/storage/emulated/0';
  List<ImageDirModel> list = [];

  @override
  initData() {
    initFile();
  }

  /// 通用可用目录
  /// getTemporaryDirectory,getApplicationCacheDirectory cache，适用于缓存文件，随时可以清除，应用程序私有目录，其他应用程序无法访问此目录。
  /// getApplicationSupportDirectory files,返回一个Future<Directory>对象，表示应用程序的支持目录,严格保密的数据。
  /// getApplicationDocumentsDirectory app_flutter,应用程序的文档目录。可持久性存储空间，通常存储用户生成的文件或其他数据。
  ///
  /// 安卓内部存储目录结构 code_cache：此目录存储 Flutter 相关代码和资源
  /// shared_prefs：SharePreferences（轻量级的本地存储） 的默认路径
  /// app_flutter/dbName：使用 sqlite（轻量级的关系型数据库） 的默认路径，sqlite也可以指定位置
  /// 安卓外部存储目录结构
  /// getExternalStorageDirectories files
  /// getExternalStorageDirectory files,应用程序可以访问顶级存储的目录的路径。仅Android可用
  /// getExternalCacheDirectories cache,存储特定于应用程序的外部缓存数据的目录的路径。
  ///
  /// 苹果可用目录
  /// getLibraryDirectory 返回应用程序的库目录。这个目录通常用于存储应用程序的共享库或插件。会报错。
  /// getTemporaryDirectory,getApplicationCacheDirectory tmp，存放临时文件，不会被备份，每三天清理一次。
  /// getApplicationDocumentsDirectory
  ///
  /// getDownloadsDirectory
  /// 存储下载文件的目录的路径，这通常仅与台式机操作系统有关。 在Android和iOS上，此函数将引发[UnsupportedError]异常。
  void initFile() {
    // getTemporaryDirectory /data/user/0/com.open.tool/cache
    // getApplicationDocumentsDirectory /data/user/0/com.open.tool/app_flutter
    // getExternalCacheDirectories /storage/emulated/0/Android/data/com.open.tool/cache
    // getExternalStorageDirectory /storage/emulated/0/Android/data/com.open.tool/cache
    requestPermission(Permission.storage).then((value) {
      if (value) {
        initOuter();
      }
    });
  }

  void initOuter() {
    list.clear();
    String imageDirStr = GSpUtils.get(GSpUtils.imageDir);
    if (imageDirStr.isNotEmpty) {
      var imageDir = json.decode(imageDirStr);
      if (imageDir != null && imageDir is List) {
        for (var element in imageDir) {
          try {
            var itemModel = ImageDirModel.fromMap(element);
            if (Directory(itemModel.path).existsSync() &&
                !itemModel.path.contains('Telegram')) {
              list.add(itemModel);
            }
          } catch (e) {}
        }
        if (list.length != imageDir.length) {
          GSpUtils.set(
              GSpUtils.imageDir,
              json.encode(list.map((model) {
                return model.toMap();
              }).toList()));
        }
      }
    }

    if (list.isEmpty) {
      Future.delayed(const Duration(milliseconds: 100), () {
        Toast.showLoading(msg: '正在查找图片，可能需要几分钟...');
        startSearch();
      });
    } else {
      notifyListeners();
    }
  }

  void startSearch() async {
    //创建一个ReceivePort
    final mainPort = ReceivePort();
    //创建isolate
    Isolate isolate = await Isolate.spawn(createIsolate, mainPort.sendPort);
    mainPort.listen((message) {
      if (message is SendPort) {
        print('ssss main主线程收到子线程发送者');
        SendPort md5Send = message;
        md5Send.send('start');
      } else {
        if (message is String) {
          // 返回的是图片地址
          if (isImage(message)) {
            File file = File(message);
            if (file.existsSync()) {
              list.add(ImageDirModel(FileUtils.getFileName(file.parent.path),
                  file.parent.path, message, true));
            }
          }
        } else {
          isolate.kill();
          Toast.close();
          GSpUtils.set(
              GSpUtils.imageDir,
              json.encode(list.map((model) {
                return model.toMap();
              }).toList()));
          notifyListeners();
        }
      }
    });
  }

  static void createIsolate(SendPort mainPort) {
    final md5Port = ReceivePort();
    //md5子线程 监听
    md5Port.listen((message) {
      //获取数据并解析
      if (message is String) {
        print('ssss md5子线程接收到消息:$message');
        if ('start' == message) {
          Directory rootDir = Directory('/storage/emulated/0');
          searchImage(rootDir, (String value) {
            if (value.isNotEmpty) {
              if ('end' == value) {
                mainPort.send(false);
              } else {
                // 返回的是图片地址
                mainPort.send(value);
              }
            }
          });
        }
      }
    });
    //md5子线程 将自己的发送者作为消息发送 这样主线程可以回复消息
    mainPort.send(md5Port.sendPort);
  }

  static searchImage(Directory rootDir, ValueChanged<String> onSearch) {
    var fileList = rootDir.listSync();
    fileList.sort((a, b) {
      if ((a is Directory && b is Directory) || (a is File && b is File)) {
        return 0;
      }
      return b is Directory ? 1 : -1;
    });
    for (var fileSystemEntity in fileList) {
      if (fileSystemEntity is Directory) {
        if (!fileSystemEntity.path.contains('Telegram')) {
          searchImage(Directory(fileSystemEntity.path), onSearch);
        }
      } else {
        if (isImage(fileSystemEntity.path)) {
          onSearch(fileSystemEntity.path);
          break;
        }
      }
    }
    if ('/storage/emulated/0' == rootDir.path) {
      onSearch('end');
    }
  }

  static isImage(String path) {
    if (FileUtils.getFileName(path).startsWith('.')) return false;
    return path.endsWith('.png') ||
        path.endsWith('.jpeg') ||
        path.endsWith('.jpg') ||
        path.endsWith('.gif');
  }

  void goImage(String dirStr) {
    Directory dir = Directory(dirStr);
    List<String> paths = [];
    var fileList = dir.listSync();
    for (var element in fileList) {
      if (isImage(element.path)) {
        paths.add(element.path);
      }
    }
    Nav.pushPage(page: ImagePage(paths, 0));
  }
}
